package cn.com.kh;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

public class KHFileUtil {
    private static final Log log = LogFactory.getLog(KHFileUtil.class);

    /**
     * @param fileContent: 写入内容
     * @param FilePath:    写入文件路径(含文件名)
     * @return boolean
     * @author LiJT
     * @description TODO 将字符串内容写入到文件
     * @date 2023-01-31 10:50
     */

    public static boolean writeFile(String fileContent, String FilePath) {

        long startTime = System.currentTimeMillis();
        long endTime = 0;
        log.debug("-File 写入本地文件参数 Start time:" + startTime + "-FilePath:" + FilePath);

        // 将文件内容写入本地服务器
        File dirAll = new File(FilePath);

        // 初始化文件对象
        FileWriter fWriter = null;
        BufferedWriter bWriter = null;
        try {
            // 文件夹路径是否存在不存在则创建
            File dir = new File(dirAll.getParent());
            if (!dir.exists()) {
                boolean flag = dir.mkdirs();
            }

            // 检查目标文件是否存在，不存在则创建
            if (!dirAll.exists()) {
                boolean flag = dirAll.createNewFile();
            }

            // 向目标文件中写入内容
            fWriter = new FileWriter(FilePath);
            bWriter = new BufferedWriter(fWriter);
            bWriter.write(fileContent);
            log.debug("-File 写入文件完成...");

        } catch (Exception e) {
            log.error("-File 写入文件失败：" + e.getMessage(), e);

        } finally {

            // 释放资源
            try {
                if (fWriter != null) {
                    fWriter.close();
                }
            } catch (Exception e) {
                log.warn("-File 文件操作对象 fWriter 释放异常-", e);
            }
            try {
                if (bWriter != null) {
                    fWriter.close();
                }
            } catch (Exception e) {
                log.warn("-File 文件操作对象 bWriter 释放异常-", e);
            }

            endTime = System.currentTimeMillis();
            log.debug("-File 写入文件结束 Start time:" + startTime + "; End time:" + endTime + "; Run Time:" + (endTime - startTime) + "(ms)");

        }

        return dirAll.exists();

    }

    /**
     * @param cmdStr: 执行命令
     * @return boolean 成功true 失败false
     * @author LiJT
     * @description TODO 执行Linux命令
     * @date 2023-01-31 10:54
     */
    public static boolean doLinuxCmd(String cmdStr) {

        log.debug("doLinuxCmd command:" + cmdStr);
        boolean flag = false;
        List<String> command = new ArrayList<>();
        command.add("/bin/sh");
        command.add("-c");
        command.add(cmdStr);
        try {
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectErrorStream(true);
            Process process = builder.start();
            LineNumberReader ir = new LineNumberReader(new InputStreamReader(process.getInputStream(), Charset.forName("UTF8")));
            String lines = new String(), line;
            while ((line = ir.readLine()) != null) {
                lines += line;
                log.debug("doLinuxCmd 执行过程:" + line);
            }
            log.debug("doLinuxCmd 执行结果:" + lines);

            if (process.isAlive()) {
                int exitcode = process.waitFor();
                if (exitcode == 0) {
                    flag = true;
                    log.debug("doLinuxCmd successfully");
                } else {
                    log.error("doLinuxCmd failed and return " + exitcode);
                }
            }
        } catch (Exception e) {
            log.error("doLinuxCmd Exception-", e);
        }
        return flag;
    }

    /**
     * @param dirPath: 文件夹路径
     * @return String 数组
     * @author LiJT
     * @description TODO 读取文件夹下所有文件和目录
     * @date 2023-01-31 11:00
     */
    public static String[] getDirList(String dirPath) {
        log.debug("getDirList 待读取路径:" + dirPath);
        String[] list = null;
        File file = new File(dirPath);
        if (file.isDirectory()) {
            log.debug("getDirList 正在读取[" + dirPath + "]目录....");
            list = file.list();
        } else {
            log.debug("getDirList[" + dirPath + "]不是一个目录。");
        }
        return list;
    }

    /**
     * 删除单个文件
     *
     * @param pathName 删除文件路径名
     * @return
     */
    public static boolean deleteFiles(String pathName) {
        boolean flag = false;
        //根据路径创建文件对象
        File file = new File(pathName);
        //路径是个文件且不为空时删除文件
        if (file.isFile() && file.exists()) {
            flag = file.delete();
        }
        //删除失败时，返回false
        return flag;
    }

    /**
     * 删除目录本身以及目录下的所有文件及文件夹
     *
     * @param pathName 目录名
     * @return
     */
    public static boolean deleteDiretory(String pathName) {
        boolean flag = false;
        //根据路径创建文件对象
        File directory = new File(pathName);
        //如果路径是一个目录且不为空时，删除目录
        if (directory.isDirectory() && directory.exists()) {
            //获取目录下的所有的目录和文件，放入数组files中
            File[] files = directory.listFiles();
            //遍历目录下的所有的文件和目录
            for (int i = 0; i < files.length; i++) {
                //如果目录下是文件时，调用deleteFiles（）方法，删除单个文件
                if (files[i].isFile()) {
                    flag = deleteFiles(files[i].getAbsolutePath());
                }//如果目录下是目录时，调用自身deleteDirectory()，形成递归调用
                else {
                    flag = deleteDiretory(files[i].getAbsolutePath());
                }
            }

            //删除目录本身，如果想要保留目录只删除文件，此句可以不要
            flag = directory.delete();
        }
        //删除成功时返回true，失败时返回false
        return flag;
    }

    /**
     * 删除文件或者目录
     *
     * @param pathName 路径名
     * @return
     */
    public static boolean deleteDirectoryOrFile(String pathName) {
        boolean flag = false;
        File file = new File(pathName);
        //如果路径是一个文件则调用deleteFiles()
        if (file.isFile() && file.exists()) {
            flag = deleteFiles(pathName);
        }//如果路径是目录则调用deleteDirectory()
        else if (file.isDirectory() && file.exists()) {
            flag = deleteDiretory(pathName);
        }

        return flag;
    }

    public static String fileToString(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return "file is not exist";
        }
        FileReader fileReader = null;
        BufferedReader bufferedReader = null;
        StringBuilder stringBuilder = new StringBuilder();
        try {
            fileReader = new FileReader(file);
            bufferedReader = new BufferedReader(fileReader);
            String temp = null;
            while ((temp = bufferedReader.readLine()) != null) {
                stringBuilder.append(temp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fileReader.close();
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return stringBuilder.toString();
    }

    public static String FileReplacement(String fileContent, String oldChar, String newChar) {

        // 生成文件路径
        String filePath = "D:\\tempFile-" + KHUtil.getRandomString(6) + "-" + System.currentTimeMillis();

        // 先将内容写入文件
        boolean writeFlag = writeFile(fileContent, filePath);
        log.debug("先将内容写入文件成功！：" + writeFlag +" 长度:"+fileContent.length());

        // 读取文件并逐行替换并写入新文件
        FileReader fReader = null;
        BufferedReader bReader = null;

        FileWriter fWriter = null;
        PrintWriter pWriter = null;

        try {
            fReader = new FileReader(filePath);
            bReader = new BufferedReader(fReader);

            fWriter = new FileWriter(filePath + "tempFile");
            pWriter = new PrintWriter(fWriter);

            String line;
            while ((line = bReader.readLine()) != null) {
                // 将需要替换的字符进行替换操作
                line = StringUtils.replace(line, oldChar, newChar);

                // 输出到临时文件
                pWriter.println(line);
            }
        } catch (IOException e) {
            log.error("发生错误：" + e.getMessage(), e);
        } finally {

            // 释放资源
            try {
                if (fReader != null) {
                    fReader.close();
                }
            } catch (Exception e) {
                log.warn("文件操作对象fReader释放异常-", e);
            }
            try {
                if (bReader != null) {
                    bReader.close();
                }
            } catch (Exception e) {
                log.warn("文件操作对象bReader释放异常-", e);
            }
            try {
                if (fWriter != null) {
                    fWriter.close();
                }
            } catch (Exception e) {
                log.warn("文件操作对象fWriter释放异常-", e);
            }
            try {
                if (pWriter != null) {
                    pWriter.close();
                }
            } catch (Exception e) {
                log.warn("文件操作对象pWriter释放异常-", e);
            }

            // 删除原始文件，重命名临时文件为原始文件名
            File originalFile = new File(filePath);
            File tempFile = new File(filePath + "tempFile");
            if (!deleteFiles(filePath) || !tempFile.renameTo(originalFile)) {
                log.warn("无法完成文件替换！" + originalFile.exists());
            } else {

                // 获取文件的绝对路径
                fileContent = fileToString(filePath);

                // 输出文件路径
                log.debug("文件替换成功！创建的文件路径是：" + filePath);
            }

        }

        return fileContent;
    }

}
